﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DailyFx.AI
{

	public abstract class  SimpleDriver : IDriver, IObserver
	{
		/// <summary>
		///		Contains all ployments to run .
		/// </summary>
		private List<IPloyment> ployments = new List<IPloyment>();

		/// <summary>
		///		Indicates if still running .
		/// </summary>
		private bool _isRunning = false;


		public SimpleDriver ( IBlackboard blackboard )
		{
			this.setBlackboard ( blackboard );
		}
		

		 public void applyPloyment ( IPloyment ployment)
		 {
			 // assert ( ployment != null && ployment is SimplePloyment)

			 if ( this.ployments.Contains( ployment ) )
				 return;

			 this.ployments.Add( ployment );
		}

		public void disposePloyment ( IPloyment ployment)
		{
			 // assert ( ployment != null && ployment is SimplePloyment )
			this.ployments.Remove ( ployment);
		}


		public bool IsRunning
		{
			get { return this._isRunning; }
		}

		public IList<IPloyment> Ployments
		{
			get { return this.ployments.AsReadOnly(); }
		}

		 protected void Run ()
		 {
			this._isRunning = true;
			try {
				while (this.RunImpl() ) ;
			}
			finally {
				this._isRunning = false;
			}
		}

		  protected bool RunImpl ()
		  {
			bool toRun = true ;

			// clone control list to allow concurrent attach and detach
			  foreach ( var ployment in ployments )
			  {
				  toRun = ployment.Run() | toRun; // short circuit operator !!
			  }
			  
			  return toRun ;
		  }



		public void setBlackboard ( IBlackboard blackboard ) 
		{
			if ( blackboard == null )
				throw new InvalidOperationException ( "Cannot bind a null blackboard");

			blackboard.registerObserver ( Guid.Empty, this );
		}



		public void OnBlockAdded ( IBlackboard blackboard, Guid zone, IBlock block )
		{
			if ( !this._isRunning )
				this.Run();
		}

		public void OnBlockRemoved ( IBlackboard blackboard, Guid zone, IBlock block )
		{
			if ( !this._isRunning ) 
				this.Run ();
		}

		public void OnBlockChanged ( IBlackboard blackboard, Guid zone, IBlock block )
		{
			if ( !this._isRunning )
				this.Run();
		}
   }

 

}
